package com.liuwei.spring.cloud.biz.service;

import com.liuwei.spring.cloud.framework.constants.CaffeineCache;
import jakarta.annotation.Resource;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.redisson.api.listener.MessageListener;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.Collection;

@Slf4j
@Service
public class CacheService {

    @Resource
    RedissonClient redissonClient;

    @Resource(name = CaffeineCache.CACHE_MANAGER)
    CacheManager caffeineCacheManager;

    /** 监听消费缓存清空事件 **/
    public static String CAFFEINE_CACHE_TOPIC = "CAFFEINE_CACHE_TOPIC";
    public void registerEvictListener(){
        RTopic topic = redissonClient.getTopic(CAFFEINE_CACHE_TOPIC);
        topic.addListener(CaffeineEvent.class,new CaffeineCacheListener());
    }

    @Async
    public void evictRedisCache(CaffeineEvent event){
        String cacheKey = event.getKey();
        redissonClient.getBucket(cacheKey).delete();
    }

    @Async
    public void evictCaffeineCache(CaffeineEvent event){
        RTopic topic = redissonClient.getTopic(CAFFEINE_CACHE_TOPIC);
        topic.publish(event);
    }

    public class CaffeineCacheListener implements MessageListener<CaffeineEvent> {
        @Override
        public void onMessage(CharSequence charSequence, CaffeineEvent caffeineEvent) {
            String cacheKey = caffeineEvent.getKey();
            Collection<String> cacheNames = caffeineCacheManager.getCacheNames();
            CollectionUtils.emptyIfNull(cacheNames).forEach(x->{
                Cache cache = caffeineCacheManager.getCache(x);
                cache.evictIfPresent(cacheKey);
            });
        }
    }

    @Data
    public class CaffeineEvent implements Serializable {
        String key;
    }
}
